version 18.0
clear
quietly log
local logon = r(status)
if "`logon'" == "on" { 
	log close 
	}
log using bsgs2026jleo-interpret, text replace


/*		************************************************************************	*/
/*     	File Name:		bsgs2026jleo-analysis.do									*/
/*     	Date:   		January 30, 2026											*/
/*      Author: 		Frederick J. Boehmke										*/
/*      Purpose:		Replication file for Boehmke, Shipan, Goehring, and 		*/
/*						Saunders JLEO article analyzing the effect of local and 	*/
/*						state legislator ideology on nursing home inspections.		*/
/*						This file interprets the models to make the figures.		*/
/*						You will need to run the analysis file to generate the 		*/
/*						saved estimates opened up by this file. 					*/
/*      Input File:		bsgs2026jleo.dta											*/
/*						bsgs2026jleo-estimates-tableXX-modelYY.ster					*/
/*      Output File:	bsgs2026jleo-analysis.log									*/
/*						figures/bsgs2026jleo-figureXX.png							*/
/*						bsgs2026jleo-interpret.dta									*/
/*		************************************************************************	*/

		/* Create the required folders if they don't exist already. */
		
capture mkdir figures


	/**************************************************************************/
	/* Figure 1: local and aggregate preference effects plotted cumulatively. */
	/**************************************************************************/

	
use bsgs2026jleo, clear
		
		/* Adjust the data sample to match analysis. */

drop if bedsocc > 1.5 & !missing(bedsocc)

		/* Create empty data set in which to store results. */
	
preserve

clear

save bsgs2026jleo-interpret, replace emptyok
			
restore
		
		/* Open estimates. */

estimates use bsgs2026jleo-estimates-table02-model02

estimates esample: bedsocc def_all govrep hospital hou_chamber loc_house_avg ///
	loc_senate_avg med_caid med_care numbeds own_govt own_nonp resfam ///
	rnhrspc stateno year
	
	keep if e(sample)

		/* All combinations with each at (roughly) p25, p50, and p75. */
	
foreach chamber of numlist -0.75 0 0.75 {
	
	foreach house of numlist -0.9 0 0.9 {
	
		foreach senate of numlist -0.9 0 0.9 {
	
			preserve
	
			margins, predict(mu) ///
				at((median) govrep ///
				  numbeds bedsocc rnhrspc med_caid med_care hospital own_nonp own_govt ///
				  (base) resfam year=2010 stateno=34  ///
				  loc_house_avg=`house' loc_senate_avg=`senate' hou_chamber=`chamber') nose
				
			matrix M = r(table)
			svmat M
			rename M1 b

			generat at_chamber = `chamber'
			generat at_house = `house'
			generat at_senate = `senate'
			*generat at_p = 2*ttail(e(N)-e(df_m),abs(_b[`var']/_se[`var'])) 
			*generat at_sig = 1 if at_p < 0.05
					
			keep b-at_senate
			drop if missing(b)
			
			append using bsgs2026jleo-interpret
			save bsgs2026jleo-interpret, replace
			
			restore
		
			}
		
		}
	
	}
		
use bsgs2026jleo-interpret, clear

		/* Describe the scenarios for the manipulations. */

generat scenario = 1 if at_chamber == 0 & at_house == 0 & at_senate == 0
replace scenario = 2 if at_chamber != 0 & at_house == 0 & at_senate == 0
replace scenario = 3 if at_chamber != 0 & at_house != 0 & at_senate == 0
replace scenario = 4 if at_chamber > 0 & at_house > 0 & at_senate != 0
replace scenario = 4 if at_chamber < 0 & at_house < 0 & at_senate != 0

		/* Is relevant manipulation at high or low value? */

generat pctile = "hi" if scenario == 2 & at_chamber > 0
replace pctile = "lo" if scenario == 2 & at_chamber < 0

replace pctile = "hi" if scenario == 3 & at_house > 0
replace pctile = "lo" if scenario == 3 & at_house < 0

replace pctile = "hi" if scenario == 4 & at_senate > 0
replace pctile = "lo" if scenario == 4 & at_senate < 0

		/* Drop non-scenario observations. */

drop if missing(scenario)

		/* Create all pairwise combinations in order */
		/* to connect from scenario to scenario. */

tempfile preds
save `preds'

drop pctile

		/* Variables for where the scenario starts. */

rename * *_begin

cross using `preds'

		/* Variables for where the scenario ends. */

rename (b-pctile) =_end

		/* Keep only relevant cases. */

keep if scenario_end == scenario_begin + 1

drop if at_chamber_begin != at_chamber_end & at_chamber_begin != 0
drop if at_house_begin != at_house_end & at_house_begin != 0

		/* Append the original predictions. */

append using `preds'

		/* Create variables for max-min illustration. */

egen b_max = max(b)
egen b_min = min(b)

generat b_diff_max = b_max - b_min

generat b_diff_x = 4.2

twoway line b scenario if scenario == 2, scheme(s1color) ///
	lcolor(gs14) lpattern(dash)  ///
 || line b scenario if scenario == 4 & at_chamber > 0,  ///
	lcolor(gs14) lpattern(dash)  ///
 || line b scenario if scenario == 4 & at_chamber < 0,  ///
	lcolor(gs14) lpattern(dash)  ///
 || pccapsym b_max b_diff_x b_min b_diff_x, ///
	color(gs14) lpattern(dash) msymbol(o) msize(small) ///
 || pcarrow b_begin scenario_begin b_end scenario_end, ///
	color(black) ///
 || scatter b scenario if scenario == 1,  ///
	mcolor(black) msize(vsmall) ///
 || scatter b scenario if scenario != 1 & pctile == "hi", ///
	mcolor(black) msize(vsmall) ///
 || scatter b scenario if scenario != 1 & pctile == "lo", ///
	mcolor(black) msize(vsmall) ///
	xlabel(0.6 " " 1 "Baseline" 2 "Change Chamber" ///
	  3 `""Change Chamber" "and Lower Rep.""' ///
	  4 `""Change Chamber" "and Lower Rep." "and Upper Rep.""' 4.5 " ", labsize(small) notick) ///
	ylabel(5.5(0.5)7, grid) yscale(range(5.25 7)) ///
	xtitle("") ///
	ytitle("Predicted Deficiencies") ///
	text(`=b[16]' 0.99 "All" "moderate", placement(w) size(small)) ///
		/* Scenario 2. */ ///
	text(5.85 1.5 "Chamber becomes" "conservative", placement(c) size(small) box fcolor(white) lwidth(none)) ///
	text(6.40 1.5 "Chamber becomes" "liberal", placement(c) size(small) box fcolor(white) lwidth(none)) ///
	text(`=(b[14] + b[18])/2' 2 "1.10", placement(c) size(vsmall) box color(gs10) fcolor(white) lwidth(thin) lcolor(gs10) margin(vsmall)) ///
		/* Scenario 3a. */ ///
	text(6.58 2.5 "...and lower representative" "becomes conservative", placement(c) size(vsmall) ) ///
	text(6.84 2.5 "...and lower representative" "becomes liberal", placement(c) size(vsmall) ) ///
	text(`=(b[17] + b[20])/2' 3 "0.14", placement(c) size(vsmall) box color(gs10) fcolor(white) lwidth(thin) lcolor(gs10) margin(vsmall)) ///
		/* Scenario 3b. */ ///
	text(5.49 2.5 "...and lower representative" "becomes conservative", placement(c) size(vsmall) ) ///
	text(5.73 2.5 "...and lower representative" "becomes liberal", placement(c) size(vsmall) ) ///
	text(`=(b[12] + b[15])/2' 3 "0.13", placement(c) size(vsmall) box color(gs10) fcolor(white) lwidth(thin) lcolor(gs10) margin(vsmall)) ///
		/* Scenario 4a. */ ///
	text(6.63 3.5 "...and upper representative" "becomes conservative", placement(c) size(vsmall) ) ///
	text(6.93 3.5 "...and upper representative" "becomes liberal", placement(c) size(vsmall) ) ///
	text(`=(b[19] + b[21])/2' 4 "0.21", placement(c) size(vsmall) box color(gs10) fcolor(white) lwidth(thin) lcolor(gs10) margin(vsmall)) ///
		/* Scenario 4d. */ ///
	text(5.40 3.5 "...and upper representative" "becomes conservative", placement(c) size(vsmall) ) ///
	text(5.67 3.5 "...and upper representative" "becomes liberal", placement(c) size(vsmall) ) ///
	text(`=(b[11] + b[13])/2' 4 "0.17", placement(c) size(vsmall) box color(gs10) fcolor(white) lwidth(thin) lcolor(gs10) margin(vsmall)) ///
		/* Max-min difference. */ ///
	text(`=(b_max[1] + b_min[1])/2' `=b_diff_x[1]' "1.44", placement(c) size(vsmall) box color(gs10) fcolor(white) lwidth(thin) lcolor(gs10) margin(vsmall)) ///
	xsize(4) ysize(3) ///
	legend(off) 
		
	graph export figures/bsgs2026jleo-figure01.png, replace width(3000)
	
		
	/****************************************************************/
	/* Figure 2: Majority party status prediction in upper chamber. */
	/****************************************************************/


use bsgs2026jleo, clear
		
		/* Adjust the data sample to match analysis. */

drop if bedsocc > 1.5 & !missing(bedsocc)

		/* Open estimates. */

estimates use bsgs2026jleo-estimates-table02-model03

estimates esample: bedsocc def_all govrep hospital hou_chamber loc_house_avg loc_house_inmaj ///
	loc_senate_avg loc_senate_inmaj med_caid med_care numbeds own_govt own_nonp resfam ///
	rnhrspc stateno year

	generat sample = e(sample)
	
	keep if e(sample)

		/* Marginal effect of majority status given upper chamber representative ideology. */

generat b_at_senate = .

generat b_maj_sen = .
generat b_maj_sen_se = .
generat b_maj_sen_ci_hi = .
generat b_maj_sen_ci_lo = .
		
generat b_min_sen = .
generat b_min_sen_se = .
generat b_min_sen_ci_hi = .
generat b_min_sen_ci_lo = .
				
local i = 1
		
forvalues ideo = -2.5(0.5)3 {	
	
	replace b_at_senate = `ideo' in `i'
	
	lincom 1.loc_senate_inmaj + (loc_senate_avg + c.loc_senate_avg#1.loc_senate_inmaj)*`ideo'					

	replace b_min_sen = r(estimate) in `i'
	replace b_min_sen_se = r(se) in `i'
	replace b_min_sen_ci_hi = r(ub) in `i'
	replace b_min_sen_ci_lo = r(lb) in `i'
	
	lincom 0 + (loc_senate_avg)*`ideo'					

	replace b_maj_sen = r(estimate) in `i'
	replace b_maj_sen_se = r(se) in `i'
	replace b_maj_sen_ci_hi = r(ub) in `i'
	replace b_maj_sen_ci_lo = r(lb) in `i'
	
	local i = `i' + 1
	
	}
	
twoway rarea b_min_sen_ci_lo b_min_sen_ci_hi b_at_senate, scheme(s1mono) ///
	color(ltblue%60) ///
 || line b_min_sen b_at_senate, ///
	lcolor(blue) ///
 || rarea b_maj_sen_ci_lo b_maj_sen_ci_hi b_at_senate, ///
	color(red%20) ///
 || line b_maj_sen b_at_senate, ///
	lcolor(red) ///
 || hist loc_senate_avg if sample==1, fraction yaxis(2) bin(100) ///
	  color(gs12) yscale(range(0.05 0.5) axis(2)) ytitle("", axis(2)) ylabel(none, axis(2)) ///
 || pcarrowi -0.06 -2.4 0.1 -2.4, color(gs5) ///
 || pcarrowi 0.07 2.9 -0.16 2.9, color(gs5) ///
 || pci -0.04 -0.45 -0.01 -0.25, color(gs5) ///
	xtitle("Upper Chamber Representative Ideology") xlabel(-2(1)3) ///
	ytitle("Change in Latent Deficiency Scale") ///
	ylabel(-0.2(0.1)0.1, grid axis(1)) ///
	yline(0, lcolor(gs10) axis(1)) ///
	text(-0.125 1.5 "Majority", placement(w) color(blue)) ///
	text(0.075 1.5 "Minority", placement(w) color(red)) ///
	text(0.02 -2.3 "A liberal representative" "moving into the majority" "increases deficiencies.", ///
	  placement(e) size(vsmall) justification(left) color(gs5)) ///
	text(-0.05  2.8 "A conservative representative" "moving into the majority" "decreases deficiencies.", ///
	  placement(w) size(vsmall) justification(right) color(gs5)) ///
	text(-0.055  -0.45 "For moderate representatives" "changing party status has little" "effect on deficiencies.", ///
	  placement(c) size(vsmall) justification(center) color(gs5)) ///
	legend(off)
	
	graph export figures/bsgs2026jleo-figure02.png, replace width(3000)

	
	/******************************************************************************/
	/* Figure SI.1: Professionalism and preferences interaction: Bowen and Greene */
	/******************************************************************************/


use bsgs2026jleo, clear
		
		/* Adjust the data sample to match analysis. */

drop if bedsocc > 1.5 & !missing(bedsocc)

		/* Open estimates. */

estimates use bsgs2026jleo-estimates-tableSI2a

estimates esample: bedsocc def_all govrep hospital hou_chamber legp_bg_cs1_ipol loc_house_avg  ///
	loc_senate_avg med_caid med_care numbeds own_govt own_nonp resfam ///
	rnhrspc stateno year

	generat sample = e(sample)
	
	keep if e(sample)
	
		/* Marginal effect of aggregate chamber ideology given professionalism. */

generat b_at_legp = .

generat b_chamber = .
generat b_chamber_se = .
generat b_chamber_ci_hi = .
generat b_chamber_ci_lo = .
		
generat b_house = .
generat b_house_se = .
generat b_house_ci_hi = .
generat b_house_ci_lo = .
		
generat b_senate = .
generat b_senate_se = .
generat b_senate_ci_hi = .
generat b_senate_ci_lo = .
		
local i = 1
		
forvalues legp = -2(0.5)8.5 {	
	
	replace b_at_legp = `legp' in `i'
	
	lincom hou_chamber + c.hou_chamber#c.legp_bg_cs1_ipol*`legp'					

	replace b_chamber = r(estimate) in `i'
	replace b_chamber_se = r(se) in `i'
	replace b_chamber_ci_hi = r(ub) in `i'
	replace b_chamber_ci_lo = r(lb) in `i'
	
	lincom loc_house_avg + c.loc_house_avg#c.legp_bg_cs1_ipol*`legp'					

	replace b_house = r(estimate) in `i'
	replace b_house_se = r(se) in `i'
	replace b_house_ci_hi = r(ub) in `i'
	replace b_house_ci_lo = r(lb) in `i'
	
	lincom loc_senate_avg + c.loc_senate_avg#c.legp_bg_cs1_ipol*`legp'					

	replace b_senate = r(estimate) in `i'
	replace b_senate_se = r(se) in `i'
	replace b_senate_ci_hi = r(ub) in `i'
	replace b_senate_ci_lo = r(lb) in `i'
	
	local i = `i' + 1
	
	}
	
twoway rarea b_chamber_ci_lo b_chamber_ci_hi b_at_legp, scheme(s1mono) ///
	color(gs13%50) ///
 || line b_chamber b_at_legp, ///
	lcolor(black) ///
 || rarea b_house_ci_lo b_house_ci_hi b_at_legp, ///
	color(ltblue%60) ///
 || line b_house b_at_legp, ///
	lcolor(blue) ///
 || rarea b_senate_ci_lo b_senate_ci_hi b_at_legp, ///
	color(red%20) ///
 || line b_senate b_at_legp, ///
	lcolor(red) ///
 || hist legp_bg_cs1_ipol if sample==1, fraction yaxis(2) bin(100) ///
	  yscale(range(0 0.5) axis(2)) ytitle("", axis(2)) ylabel(none, axis(2)) ///
	ylabel(-0.2(0.1)0.2, grid axis(1)) ///
	yline(0, lcolor(gs10)) ///
	xtitle("Legislative Professionalism") xlabel(-2(2)8) ///
	ytitle(Marginal Effect of Ideology) ///
	text( 0 -1.8 "Increased professionalism diminishes" "individual preferences", placement(ne) size(small)) ///
	text(-0.185 0 "Increased professionalism diminishes" "collective preferences", placement(ne) size(small)) ///
	text(-0.05 -2 "Upper Rep.", placement(se) size(vsmall) color(red)) ///
	text(-0.005 -2 "Lower Rep.", placement(se) size(vsmall) color(blue)) ///
	text(-0.145 -2 "Chamber", placement(e) size(vsmall) color(black)) ///
	legend(off)
	
	graph export figures/bsgs2026jleo-figureSI01.png, replace width(3000)


log close
clear
exit, STATA
